package org.csu.mybigpro.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.csu.mybigpro.domain.CourseResource;
import org.csu.mybigpro.service.CourseResourceService;
import org.csu.mybigpro.util.MinioUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/resources")
public class CourseResourceController {

    @Autowired
    private CourseResourceService courseResourceService;

    @Autowired
    private MinioUtil minioUtil;

    // 上传资源接口（POST）
    @PostMapping("/upload")
    public ResponseEntity<String> uploadResource(@RequestParam("file") MultipartFile file,
                                                 @RequestParam(value = "courseId", required = false) Long courseId) {
        if (file.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("上传文件不能为空");
        }

        try {
            // MinioUtil 已经处理了生成唯一文件名并上传
            String minioUrl = minioUtil.uploadFile(file); // 这个方法会返回完整的 Minio URL，例如：http://.../bucket/uniqueUUID.ext

            String originalFilename = file.getOriginalFilename(); // 用户上传的原始文件名，例如 "图片.docx"
            String resourceType = getFileType(originalFilename); // 根据原始文件名判断类型

            CourseResource courseResource = new CourseResource();
            courseResource.setTitle(originalFilename); // 资源标题，通常是原始文件名

            // 【重要修改点】：确保 filename 存储 Minio 生成的唯一文件名（包含UUID）
            // MinioUtil.uploadFile 返回的 URL 已经包含了 Minio 中存储的唯一文件名
            // 因此从 Minio URL 中提取 Minio 上的对象名作为数据库的 filename
            String minioObjectName = minioUtil.getObjectNameFromUrl(minioUrl);
            if (minioObjectName == null) {
                // 这是一个备用方案，理论上 MinioUtil 应该总能解析成功
                minioObjectName = minioUrl.substring(minioUrl.lastIndexOf('/') + 1);
            }
            courseResource.setFilename(minioObjectName); // 数据库中存储的唯一文件名，例如 "95b83a97f9b344498a2b4d13ed2e46fad.docx"
            courseResource.setResourceType(resourceType);
            courseResource.setUploadTime(LocalDateTime.now());
            courseResource.setShared(false); // 默认不共享
            courseResource.setEditable(true); // 默认可编辑
            courseResource.setFilePath(minioUrl); // 存储完整的 Minio 访问路径

            // 如果提供了 courseId，则设置
            if (courseId != null) {
                courseResource.setCourseId(courseId);
            }

            courseResourceService.save(courseResource);

            return ResponseEntity.status(HttpStatus.CREATED).body("资源上传成功，ID: " + courseResource.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("上传资源失败: " + e.getMessage());
        }
    }

    // 下载/预览资源接口（GET） - 通过后端代理从 Minio 下载
    // 使用资源 ID 访问，更安全且方便管理
    @GetMapping("/download/{id}")
    public ResponseEntity<Resource> downloadResource(@PathVariable Long id,
                                                     @RequestParam(value = "preview", defaultValue = "false") boolean preview) { // <-- 【新增】preview 参数
        CourseResource resource = courseResourceService.getById(id);
        if (resource == null || resource.getFilePath() == null || resource.getFilePath().isEmpty()) {
            return ResponseEntity.notFound().build();
        }

        try {
            String minioUrl = resource.getFilePath();
            // 从 Minio URL 中解析出 bucketName 和 objectName
            String bucketName = minioUtil.getBucketNameFromUrl(minioUrl);
            String objectName = minioUtil.getObjectNameFromUrl(minioUrl); // 这是 MinIO 中的唯一文件名（含UUID）

            if (bucketName == null || objectName == null) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); // URL 解析失败
            }

            // 从 Minio 下载文件流
            InputStream inputStream = minioUtil.downloadFile(bucketName, objectName);
            byte[] fileBytes = inputStream.readAllBytes(); // 读取所有字节
            ByteArrayResource minioResource = new ByteArrayResource(fileBytes);

            // 【修改点】：使用资源的 title 作为用户友好的文件名
            String userFriendlyFilename = resource.getTitle();
            // 备用：如果 title 为空，则使用 MinIO 的对象名
            if (userFriendlyFilename == null || userFriendlyFilename.isEmpty()) {
                userFriendlyFilename = objectName;
            }

            // 对文件名进行 URL 编码，防止中文乱码，并替换 + 为 %20 (空格)
            String encodedFileName = URLEncoder.encode(userFriendlyFilename, StandardCharsets.UTF_8.toString()).replace("+", "%20");

            HttpHeaders headers = new HttpHeaders();
            // 【关键修改点】：根据 preview 参数设置 Content-Disposition
            if (preview) {
                // 对于预览，设置为 inline，浏览器会尝试在标签页中显示
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + encodedFileName + "\"");
            } else {
                // 对于下载，设置为 attachment，浏览器会弹出下载框
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");
            }

            // 根据文件类型设置 Content-Type，如果无法判断则使用默认的八进制流
            // 【修改点】：将 userFriendlyFilename 传递给 getMediaTypeForFileName
            MediaType mediaType = getMediaTypeForFileName(userFriendlyFilename);
            if (mediaType != null) {
                headers.setContentType(mediaType);
            } else {
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 默认二进制流
            }

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(fileBytes.length) // 设置文件长度
                    .body(minioResource);

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); // 返回通用错误
        }
    }

    // 删除资源接口（DELETE）
    @DeleteMapping("/{id}")
    public ResponseEntity<String> deleteResource(@PathVariable Long id) {
        try {
            CourseResource resource = courseResourceService.getById(id);
            if (resource != null && resource.getFilePath() != null && !resource.getFilePath().isEmpty()) {
                // 从 Minio URL 中解析出 bucketName 和 objectName
                String minioUrl = resource.getFilePath();
                String bucketName = minioUtil.getBucketNameFromUrl(minioUrl);
                String objectName = minioUtil.getObjectNameFromUrl(minioUrl); // 这应该是 Minio 中的唯一文件名

                if (bucketName != null && objectName != null) {
                    minioUtil.deleteFile(bucketName, objectName);
                } else {
                    System.err.println("无法从 URL 解析 Minio 存储桶和对象名，跳过 Minio 文件删除: " + minioUrl);
                }
            } else {
                System.err.println("资源文件路径为空，跳过Minio文件删除: " + id);
            }

            courseResourceService.removeById(id);

            return ResponseEntity.ok("资源删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("删除资源失败: " + e.getMessage());
        }
    }


    // 辅助方法：根据文件名获取 MediaType
    private MediaType getMediaTypeForFileName(String fileName) {
        String ext = "";
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0) {
            ext = fileName.substring(lastDotIndex + 1).toLowerCase();
        }
        return switch (ext) {
            case "pdf" -> MediaType.APPLICATION_PDF;
            case "doc", "docx" -> MediaType.valueOf("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            case "xls", "xlsx" -> MediaType.valueOf("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            case "ppt", "pptx" -> MediaType.valueOf("application/vnd.openxmlformats-officedocument.presentationml.presentation");
            case "jpg", "jpeg" -> MediaType.IMAGE_JPEG;
            case "png" -> MediaType.IMAGE_PNG;
            case "gif" -> MediaType.IMAGE_GIF;
            case "mp4" -> MediaType.valueOf("video/mp4");
            case "mp3" -> MediaType.valueOf("audio/mpeg");
            case "txt" -> MediaType.TEXT_PLAIN;
            case "html", "htm" -> MediaType.TEXT_HTML;
            case "css" -> MediaType.valueOf("text/css");
            case "js" -> MediaType.valueOf("application/javascript");
            case "json" -> MediaType.APPLICATION_JSON;
            case "zip" -> MediaType.valueOf("application/zip");
            case "rar" -> MediaType.valueOf("application/x-rar-compressed");
            default -> null; // 如果无法识别，则返回 null
        };
    }

    // 文件类型判断辅助方法 (用于存储到数据库中的 resourceType 字段)
    private String getFileType(String filename) {
        String ext = "";
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex > 0) {
            ext = filename.substring(lastDotIndex + 1).toLowerCase();
        }

        return switch (ext) {
            case "pdf", "doc", "docx" -> "文档";
            case "ppt", "pptx" -> "课件";
            case "mp4", "avi", "mov", "webm", "mkv", "flv" -> "视频";
            case "jpg", "jpeg", "png", "gif", "bmp", "svg", "webp", "ico" -> "图片";
            case "zip", "rar", "7z", "tar", "gz" -> "压缩包";
            case "xls", "xlsx", "csv" -> "Excel";
            case "txt" -> "文本";
            case "mp3", "wav", "aac", "flac" -> "音频";
            default -> "其他";
        };
    }

    // 获取所有资源列表（GET），支持查询参数
    @GetMapping
    public ResponseEntity<List<CourseResource>> listResources(
            @RequestParam(value = "courseId", required = false) Long courseId,
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "resourceType", required = false) String resourceType) {

        LambdaQueryWrapper<CourseResource> queryWrapper = new LambdaQueryWrapper<>();

        if (courseId != null) {
            queryWrapper.eq(CourseResource::getCourseId, courseId);
        }
        if (title != null && !title.isEmpty()) {
            queryWrapper.like(CourseResource::getTitle, title); // 模糊查询标题
        }
        if (resourceType != null && !resourceType.isEmpty()) {
            queryWrapper.eq(CourseResource::getResourceType, resourceType);
        }

        List<CourseResource> resources = courseResourceService.list(queryWrapper);
        return ResponseEntity.ok(resources);
    }
}